// WebSocket service for real-time preview
const WS_BASE_URL = 'ws://localhost:3000';

class WebSocketService {
  constructor() {
    this.ws = null;
    this.listeners = {};
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
    this.reconnectDelay = 1000;
  }

  connect(taskId) {
    const wsUrl = `${WS_BASE_URL}/preview/${taskId}`;
    
    return new Promise((resolve, reject) => {
      try {
        this.ws = new WebSocket(wsUrl);
        
        this.ws.onopen = (event) => {
          console.log('WebSocket connection opened:', event);
          this.reconnectAttempts = 0;
          this.emit('open', event);
          resolve(this.ws);
        };
        
        this.ws.onmessage = (event) => {
          try {
            const data = JSON.parse(event.data);
            this.handleMessage(data);
          } catch (error) {
            // If not JSON, treat as binary data (image frame)
            this.emit('frame', event.data);
          }
        };
        
        this.ws.onclose = (event) => {
          console.log('WebSocket connection closed:', event);
          this.emit('close', event);
          
          // Attempt to reconnect if needed
          if (!event.wasClean && this.reconnectAttempts < this.maxReconnectAttempts) {
            setTimeout(() => {
              this.reconnectAttempts++;
              this.connect(taskId);
            }, this.reconnectDelay * this.reconnectAttempts);
          }
        };
        
        this.ws.onerror = (error) => {
          console.error('WebSocket error:', error);
          this.emit('error', error);
          reject(error);
        };
      } catch (error) {
        console.error('Failed to create WebSocket connection:', error);
        reject(error);
      }
    });
  }
  
  handleMessage(data) {
    switch (data.type) {
      case 'frame':
        this.emit('frame', data.payload);
        break;
      case 'status':
        this.emit('status', data.payload);
        break;
      case 'error':
        this.emit('error', data.payload);
        break;
      default:
        this.emit('message', data);
    }
  }
  
  disconnect() {
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }
  
  send(data) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(data));
    }
  }
  
  on(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }
  
  off(event, callback) {
    if (this.listeners[event]) {
      this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
    }
  }
  
  emit(event, data) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(callback => callback(data));
    }
  }
}

export default new WebSocketService();